package com.wlp.consumer.task;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.wlp.consumer.ProviderService;
import com.wlp.consumer.common.RedisUtil;
import com.wlp.consumer.dao.RedisDelayDao;
import com.wlp.consumer.model.People;
import com.wlp.consumer.model.RedisDelay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;

import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: wanglp
 */
@Component
public class RankTask {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RedisDelayDao redisDelayDao;

    private final String KEY = "rank";
    private final int DELAY = 1000;

    public void rank(){
//        IntStream.range(1,2).parallel()
//                .forEach(i->{
//                    Double d = RandomUtil.randomDouble(10,100,2, RoundingMode.CEILING);
//                    redisUtil.zSet(KEY,i,d);
//                    //System.out.println(System.currentTimeMillis()+"写入"+ JSONUtil.toJsonStr(new People().setId(i).setScore(d)));
//                });
    }

    @Scheduled(fixedDelay = DELAY)
    public void look(){
        final long it = System.currentTimeMillis();
        Mono.fromRunnable(()-> lookRank(2,it)).subscribeOn(Schedulers.newParallel("rank",10)).subscribe();
        Mono.fromRunnable(()-> lookRank(1,it)).subscribeOn(Schedulers.newParallel("rank",10)).subscribe();
        Mono.fromRunnable(()-> lookRank(0,it)).subscribeOn(Schedulers.newParallel("rank",10)).subscribe();
    }
    public void lookRank(int type,long inTime){
        Set<ZSetOperations.TypedTuple<Object>> so;
        String title ;
        switch (type){
            case 1:{
                //sg 新加坡
                title="新加坡";
                so = redisUtil.sGZSetRevRangeWithScores(KEY,0,10);
                break;
            }
            case 2:{
                // 美西
                title="美州西";
                so = redisUtil.oregonZSetRevRangeWithScores(KEY,0,10);
                break;
            }
            default:{ //德国
                title="德国主";
                so = redisUtil.zSetRevRangeWithScores(KEY,0,10);
            }
        }

        final String finalTitle = title;
        Optional.ofNullable(so).ifPresent(set->{
//            set.stream().forEach(o->{
//                People p = new People();
//                p.setId((Integer) o.getValue()).setScore(o.getScore());
//                build(inTime,p,type,finalTitle);
//            });
//            build(inTime,so,type,finalTitle);
            System.out.println(finalTitle +inTime+"-"+System.currentTimeMillis()+"top10:"+JSONUtil.toJsonStr(set.stream().map(o->{
                People p = new People();
                p.setId((Integer) o.getValue()).setScore(o.getScore());
                return p;
            }).collect(Collectors.toList())));
        });
        so.clear();
    }
    public static Map<String,String> peopleList = new ConcurrentHashMap<>(100);
    public void build(long ct,People people,int type,String title){
        String key = type + "-" + people.getId();
        if(type!=0){
            if(peopleList.containsKey(key)){
                String[] tv = peopleList.get(key).split("-");
                double score = Double.parseDouble(tv[1]);
                if(score != people.getScore()){
                    String de = 0 + "-" + people.getId();
                    if(peopleList.containsKey(de)){
                        String[] dev = peopleList.get(de).split("-");
                        long dev_last = Long.valueOf(dev[0]);
                        double dev_score = Double.parseDouble(dev[1]);
                        if(dev_score == people.getScore()){
                            redisDelayDao.insert(new RedisDelay().setDelay(Math.toIntExact(ct - dev_last - DELAY)).setArea(title));
                        }
                    }
                }
            }
        }
        if(peopleList.containsKey(key)){
            String[] tv = peopleList.get(key).split("-");
            double score = Double.valueOf(tv[1]);
            if(score != people.getScore()){
                peopleList.put(key,ct+ "-" + people.getScore());
            }
        }else {
            peopleList.put(key,ct+ "-" + people.getScore());
        }
    }
    public void build(long ct,Set<ZSetOperations.TypedTuple<Object>> so,int type,String title){
        String rankStr = so.stream().sorted(Comparator.comparing(ZSetOperations.TypedTuple::getScore))
                .map(o->o.getValue()+":"+o.getScore()).collect(Collectors.joining("|"));
        String key = String.valueOf(type);
        if(type!=0){
            if(peopleList.containsKey(key)){
                String[] tv = peopleList.get(key).split("-");
                String score = tv[1];
                if(!score.equals(rankStr)){
                    String de = "0";
                    if(peopleList.containsKey(de)){
                        String[] dev = peopleList.get(de).split("-");
                        long dev_last = Long.valueOf(dev[0]);
                        String dev_score = dev[1];
                        if(dev_score.equals(rankStr)){
                            redisDelayDao.insert(new RedisDelay().setDelay(Math.toIntExact(ct - dev_last - DELAY)).setArea(title));
                        }
                    }
                }
            }
        }
        if(peopleList.containsKey(key)){
            String[] tv = peopleList.get(key).split("-");
            String score = tv[1];
            if(!score.equals(rankStr)){
                peopleList.put(key,ct+ "-" + rankStr);
            }
        }else {
            peopleList.put(key,ct+ "-" + rankStr);
        }
    }
}
